#include "sys.h"




sys::sys()
{
	headerfile  = "parameter.h";
	defaultfile = "plist.txt";
	namelength  = 18;
	if_c_d_rc   = true;
	n_bool      = 0;
	n_int       = 0;
	n_real      = 0;
	bps.clear();
	ips.clear();
	rps.clear();
	bps_name.clear();
	ips_name.clear();
	rps_name.clear();
	pint.clear();
}




sys::sys(char* file)
{
	headerfile = file;
	n_bool      = 0;
	n_int       = 0;
	n_real      = 0;
	bps.clear();
	ips.clear();
	rps.clear();
	bps_name.clear();
	ips_name.clear();
	rps_name.clear();
	pint.clear();
	
	initialize(headerfile);
}




void sys::read(char* file)
{
	char c;
	string s, s1, s2;
	string name_type1 = "type1";
	string name_type2 = "type2";
	string name_bool  = "bool";
	string name_int   = "int";
	string name_real  = "real";
	bool b_temp;
	int n1, n2, i_temp;
	unsigned int i;
	real r1, r2, r3, r_temp;
	istringstream iss;
	c_d_rc c_d_rc0;
	
	ifstream in(file, ifstream::in);
	
	if(!in){											// if input file not exist, creat one
		cout<<"warning: file "<<file<<" does not exist, do you want to creat it?(y/n)";
		if((cin>>c) && (c=='y' || c=='Y')){
			creat(file);
		}
		else {
			cout<<"error: no parameter file\n";
			exit(2);
		}
	}
	else {
		for (; getline(in, s);) {
			if(s[0]=='#' || s[0]=='$' || s[0]=='/' || s.empty())continue;
			s1.clear();
			s2.clear();
			iss.clear();
			iss.str(s);
			iss>>s1>>s2;
			if(s1 == name_type1 && s2 == name_type2)break;
			if(s1 == name_bool && iss>>b_temp){
				for(i=0; i<bps.size(); i++)if(s2 == bps_name[i]) bps[i] = b_temp;
			}
			else if(s1 == name_int && iss>>i_temp){
				for(i=0; i<ips.size(); i++)if(s2 == ips_name[i]) ips[i] = i_temp;
			}
			else if(s1 == name_real && iss>>r_temp){
				for(i=0; i<rps.size(); i++)if(s2 == rps_name[i]) rps[i] = r_temp;
			}
			else {
				_errorstatement2_;
				exit(3);
			}
		}
		
		for (; if_c_d_rc && getline(in, s);){						// read pair interaction parameters
			if(s[0]=='#' || s[0]=='$' || s[0]=='/')continue;
			iss.clear();
			iss.str(s);
			if(!(iss>>n1>>n2>>r1>>r2>>r3)){
				_errorstatement2_;
				exit(3);
			}
			else {
				c_d_rc0.t1  = n1;
				c_d_rc0.t2  = n2;
				c_d_rc0.ccc = r1;
				c_d_rc0.ddd = r2;
				c_d_rc0.rc  = r3;
				pint.push_back(c_d_rc0);
			}
		}
		
	}
	
	display();
	
	in.close();
}




void sys::read()
{
	read(defaultfile);
}




void sys::write(char *file)
{
	ofstream wfile(file);
	
	wfile<<"# Don't change variable name or alter the order by hand!"<<endl;
	
	output(wfile);
	
	wfile.close();	
}




void sys::write()
{
	write(defaultfile);
}




void sys::display()
{
	output(cout);
}




void sys::output(ostream& write)					// Implementation of parameter output
{
	int i, j;

	for (i=0; i<n_bool; i++) {
		write<<"bool  "<<bps_name[i];
		for (j = 0; j < max(1,namelength-int(bps_name[i].size())); j++)write<<' ';
		write<<bps[i]<<endl;
	}
	
	for (i=0; i<n_int; i++) {
		write<<" int  "<<ips_name[i];
		for (j = 0; j < max(1,namelength-int(ips_name[i].size())); j++)write<<' ';
		write<<ips[i]<<endl;
	}
	
	for (i=0; i<n_real; i++) {
		write<<"real  "<<rps_name[i];
		for (j = 0; j < max(1,namelength-int(rps_name[i].size())); j++)write<<' ';
		write<<rps[i]<<endl;
	}
	if(if_c_d_rc){
		write<<endl<<"type1 type2 ccc  ddd   rc"<<endl;
		for (unsigned int ii=0; ii<pint.size(); ii++) {
			write<<"   "<<pint[ii].t1<<"     "<<pint[ii].t2<<"   "<<pint[ii].ccc<<"    "<<pint[ii].ddd<<"    "<<pint[ii].rc<<endl;
		}
	}
}




void sys::creat(char *file)
{
	string s;
	int i, n1, n2;
	real r1, r2, r3;
	c_d_rc c_d_rc0;
	istringstream iss;
		
	cin.ignore(256,'\n');
	for (i=0; i<n_bool; i++) {
		cout<<bps_name[i]<<"= ";
		getline(cin, s);
		if(s[0] == 0){
			cout<<bps[i]<<endl;
			continue;
		}
		if(s == "true" || s == "1"){
			bps[i] = true;
		}
		else if(s == "false" || s == "0"){
			bps[i] = false;
		}
		else {
			_errorstatement1_;
			exit(1);
		}
	}
	
	for (i=0; i<n_int; i++) {
		cout<<ips_name[i]<<"= ";
		getline(cin, s);
		if(s[0] == 0){
			cout<<ips[i]<<endl;
			continue;
		}
		iss.clear();
		iss.str(s);
		if(!(iss>>ips[i]) || ips[i]<=0){
			_errorstatement1_;
			exit(1);
		}
	}
	
	for (i=0; i<n_real; i++) {
		cout<<rps_name[i]<<"= ";
		getline(cin, s);
		if(s[0] == 0){
			cout<<rps[i]<<endl;
			continue;
		}
		iss.clear();
		iss.str(s);
		if(!(iss>>rps[i]) || rps[i]<=0.){
			_errorstatement1_;
			exit(1);
		}
	}
	
	if(if_c_d_rc){
		cin.ignore(256,'\n');
		cout<<endl<<"type_1 type_2 ccc ddd rc:"<<endl;
		for (; getline(cin, s);){
			iss.clear();
			iss.str(s);
			if(iss>>n1>>n2>>r1>>r2>>r3){
				c_d_rc0.t1  = n1;
				c_d_rc0.t2  = n2;
				c_d_rc0.ccc = r1;
				c_d_rc0.ddd = r2;
				c_d_rc0.rc  = r3;
				pint.push_back(c_d_rc0);
			}
			else {
				break;
			}
		}
	}
	write(file);
}




void sys::initialize()
{
	initialize(headerfile);
}




void sys::initialize(char* file)
{
	bool comment_mode = false, define_mode = false;
	unsigned int i;
	string s, s_temp, s1, s2;
	string name_class = "class";
	string name_bool  = "bool";
	string name_int   = "int";
	string name_real  = "real";
	istringstream iss;
	
	ifstream in(file, ifstream::in);
	
	if(!in){
		cout<<"error: header file "<<file<<"does not exist"<<endl;
		exit(-1);
	}
	
	for(; getline(in, s);){
		if(s[0] == '#' || (s[0] == '/' && s[1] == '/') || s.empty())continue;
		if(s[0] == '/' && s[1] == '*'){
			comment_mode = true;
		}
		s1.clear();
		s2.clear();
		iss.clear();
		iss.str(s);
		iss>>s1>>s2;
		if( s1 == name_class && s2 == cname ){
			define_mode = true;
			continue;
		}
		for( i = 0; i < s2.size(); i++) if( s2[i]=='(' ) define_mode = false;
		if( !comment_mode && define_mode && s[0] == '}' && s[1] == ';'){
			define_mode = false;
			break;
		}
		if(!comment_mode && define_mode){
			if(s1 == name_bool){
				s2.resize(s2.size()-1);
				n_bool++;
				bps_name.push_back(s2);
			}
			else if(s1 == name_int){
				s2.resize(s2.size()-1);
				n_int++;
				ips_name.push_back(s2);
			}
			else if(s1 == name_real){
				s2.resize(s2.size()-1);
				n_real++;
				rps_name.push_back(s2);
			}
		}
		for (i = 0; i<s.size()-1; i++) {
			if (s[i] == '/' && s[i+1] == '*')comment_mode = true;
			if (comment_mode && s[i] == '*' && s[i+1] == '/')comment_mode = false;
		}
	}
	bps.resize(n_bool);
	ips.resize(n_int);
	rps.resize(n_real);
	in.close();
}




void sys::creat()
{
	creat(defaultfile);
}
